#ifndef BOOTSTRAPPING_CONTEXTCHAIN_H
#define BOOTSTRAPPING_CONTEXTCHAIN_H
#include "transform.h"

/* *
 * @class ContextChain
 * @brief  本对象管理着一个包含多套参数和其对应的计算器的列表，列表中的明文模数分别是
 * p、p^2、...、p^e（在数字提取过程中用到）。
 */
class ContextChain {
    std::vector<Context> contexts;
    std::vector<std::unique_ptr<Evaluator>> evaluators;

    static void ConvertNegOnes(uint64_t *data, size_t len, const uint64_t &from, const uint64_t &to);

public:
    ContextChain(const Context &baseContext, size_t e);
    ContextChain(const ContextChain &) = delete;
    ContextChain(ContextChain &&) = default;
    ~ContextChain() = default;

    size_t PolyModulusDegree() const;
    const Context &GetContext(size_t i) const;
    Evaluator &GetEvaluator(size_t i) const;
    size_t Size() const;
    /*
     * The base context is the first context in the chain, i.e. the one with plaintext
     * modulus p
     */
    Context &BaseContext() const;

    /*
     * The "target context" is the final context in the chain, i.e. the one with plaintext
     * modulus p^e
     */
    Context &TargetContext() const;

    Evaluator &TargetEvaluator() const;
    /*
     * Converts a secret key for one of the contexts to a secret key for the target context
     */
    void ConvertSk(const SecretKey &source, SecretKey &destination) const;

    /*
     * Converts a secret key for one of the contexts to the plaintext space of the target context
     */
    void ConvertSkPlain(const SecretKey &source, Plaintext &destination) const;

    /*
     * Converts a ciphertext for the first/base context to the plaintext space of the target context
     */
    void ConvertCiphertextPlain(const Ciphertext &source, Plaintext *destination) const;
};
#endif